官方 Demo:https://vueuse.org/core/useMouse/
先拔掉幾個參數,實作一個簡易版本,之後再把其餘參數 & 功能新增進來。
// src/compositions/useMouse.js
import { ref } from 'vue'
import { useEventListener } from '@/compositions/useEventListener'
import { defaultWindow } from '@/helper'
const UseMouseBuiltinExtractors = {
page: event => [event.pageX, event.pageY],
client: event => [event.clientX, event.clientY],
screen: event => [event.screenX, event.screenY],
}
export function useMouse(options = {}) {
const {
type = 'page',
initialValue = { x: 0, y: 0 },
window = defaultWindow,
target = window,
} = options
const x = ref(initialValue.x)
const y = ref(initialValue.y)
const extractor = typeof type === 'function'
? type
: UseMouseBuiltinExtractors[type]
const mouseHandler = (event) => {
const result = extractor(event)
if (result) {
[x.value, y.value] = result
}
}
const mouseHandlerWrapper = event => mouseHandler(event)
if (target) {
const listenerOptions = { passive: true }
useEventListener(target, ['mousemove', 'dragover'], mouseHandlerWrapper, listenerOptions)
}
return {
x,
y,
}
}
可以看到整個 useMouse 流程的開始是在之前實作的 useEventListener
,這邊是在 target 身上加 mousemove, dragover 的事件監聽,觸發事件的時候執行 mouseHandlerWrapper
,並傳入 listenerOptions
。
listenerOptions
有 { passive: true }
的設定,來告訴瀏覽器,事件監聽器永遠不會呼叫 preventDefault(),來提高效能。
而 mouseHandlerWrapper
listener 被觸發的時候會呼叫 event => mouseHandler(event)
。
mouseHandler
就是最後更新 x、y 值的地方,接著來看看這次的重點: extractor(event)
// src/compositions/useMouse.js
// ...略
const UseMouseBuiltinExtractors = {
page: event => [event.pageX, event.pageY],
client: event => [event.clientX, event.clientY],
screen: event => [event.screenX, event.screenY],
}
const extractor = typeof type === 'function'
? type
: UseMouseBuiltinExtractors[type]
// ...略
我們現在 type 的預設值是 page,extractor('page')
會拿到 event => [event.pageX, event.pageY]
,所以我們最後回傳出去的 x、y 值就是 event.pageX
、event.pageY
。
看到官網 Demo 的 Custom Extractor 區塊,type 可以傳入 function event => [event.offsetX, event.offsetY]
,以官網 Demo 的用法來說,target 傳入的是 Demo 區塊底下那塊灰色的 element,[event.offsetX, event.offsetY]
坐標是相對於觸發事件的目標元素(灰色 element)的左上角 (0, 0) 計算的,所以最終的結果就會像官網 Demo 那樣。
今天就先寫到這邊,明天開始會把 useMouse 的其他參數加進來一起看~